package com.myschool.server.dao.support;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.stereotype.Repository;

import com.myschool.server.model.BaseEntity;

@Repository("baseDao")
public abstract class BaseEntityDaoHibernate<T extends BaseEntity> extends
		GenericDaoHibernate<T> implements BaseEntityDao<T> {

	@Autowired
	@Required
	public void init(SessionFactory factory) {
		setSessionFactory(factory);
	}

	/**
	 * Return the entity with the given entity id.
	 * 
	 * @param identity
	 *            the entity id of the object required.
	 * @return The object with the given ID.
	 */
	public T get(Long identity) {
		return (T) getHibernateTemplate().get(persistentClass, identity);
	}

	/**
	 * Constructor that takes in a class to determine what type of entity is to
	 * be persisted.
	 * 
	 * @param persistentClass
	 *            the class type which is to be persisted.
	 */
	public BaseEntityDaoHibernate(final Class<T> persistentClass) {
		super(persistentClass);
	}

	/**
	 * {@inheritDoc}
	 */
	public T save(final T object) {
		if (object.getEntityId() == null) {
			getHibernateTemplate().saveOrUpdate(object);
			return object;
		} else {
			return (T) getHibernateTemplate().merge(object);
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	public T findByName(final String name) {
		return (T) getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session session) {
				Criteria crit = session.createCriteria(persistentClass);
				crit.add(Restrictions.eq("name", name));
				return crit.uniqueResult();
			}
		});
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	@SuppressWarnings("unchecked")
	public List<T> searchByNameSubstring(final String searchFor) {
		if (StringUtils.isBlank(searchFor)) {
			return new ArrayList<T>();
		}
		return (List<T>) getHibernateTemplate().execute(
				new HibernateCallback() {
					public Object doInHibernate(Session session) {
						Criteria crit = session.createCriteria(persistentClass);
						crit.add(Restrictions.ilike("name",
								'%' + searchFor + '%'));
						return crit.list();
					}
				});
	}
}
